#pragma once

#include <iostream>
#include <memory>
#include <unordered_map>
#include "Epoller.hpp"
#include "Connection.hpp"

class Reactor
{
    static const int revs_num = 128;

private:
    //判断Connection是否存在
    bool IsConnectionExists(std::shared_ptr<Connection> &conn)
    {
        for (auto item : _connections)
        {
            if (item.second == conn)
            {
                return true;
            }
        }
        return false;
    }
    //判断套接字是否存在
    bool IsSocketfdExist(int sockfd)
    {
        auto iter = _connections.find(sockfd);
        if (iter == _connections.end())
        {
            return false;
        }
        return true;
    }

    //判断_connections是否为空
    bool IsEmpty(const std::unordered_map<int, std::shared_ptr<Connection>> &connections)
    {
        if (connections.size() == 0)
        {
            return true;
        }
        return false;
    }

    //监听所有绑定的套接字,返回激活套接字的值,被激活的套接字存储在_revs中
    int LoopOnce(int timeout)
    {
        return _epoller_ptr->WaitEvent(_revs, revs_num, timeout);
    }

    //根据返回套接字的数量循环遍历_revs,根据epoll_event的事件调用Connection对应的函数
    void DisPatcher(int n)
    {
        for (int i = 0; i < n; i++)
        {
            int sockfd = _revs[i].data.fd;
            uint32_t revents = _revs[i].events;
            if (revents & EPOLLERR)
                revents |= (EPOLLIN | EPOLLOUT);
            if (revents & EPOLLHUP)
                revents |= (EPOLLIN | EPOLLOUT);
            if (revents & EPOLLIN)
            {
                if (IsSocketfdExist(sockfd))
                    _connections[sockfd]->Recver();
            }
            if (revents & EPOLLOUT)
            {
                if (IsSocketfdExist(sockfd))
                    _connections[sockfd]->Sender();
            }
        }
    }

public:
    //构建一个epoll监听服务
    Reactor() : _epoller_ptr(std::make_unique<Epoller>()), _isrunning(false)
    {
    }

    //循环打印绑定的套接字,并且每隔一秒返回一次激活的套接字,根据数量配发任务
    void Loop()
    {
        if (IsEmpty(_connections))
        {
            return;
        }
        _isrunning = true;
        while (_isrunning)
        {
            PrintConnection();
            int n = LoopOnce(1000);
            DisPatcher(n);
        }
        _isrunning = false;
    }

    //将conn的Connection添加到_connection,并且配置_epoll_ptr和conn的所属Reactor
    void AddConnection(std::shared_ptr<Connection> &conn)
    {
        if (IsConnectionExists(conn))
        {
            LOG(LogLevel::ERROR) << "CONNECTION HAS EXISTED";
            return;
        }
        uint32_t events = conn->GetEvent();
        int sockfd = conn->GetSockFd();
        _epoller_ptr->AddEvent(sockfd, events);
        conn->SetOwner(this);
        _connections[sockfd] = conn;
    }

    //修改对应套接字的读监听和写监听
    void EnableReadWrite(int sockfd,bool enableread,bool enablewrite)
    {
        if(!IsSocketfdExist(sockfd))
        {
            LOG(LogLevel::WARNING)<<"ENABLEREADWRITE,CONN IS EXISTS";
            return;
        }
        uint32_t new_event=(EPOLLET|(enableread?EPOLLIN:0)|(enablewrite?EPOLLOUT:0));
        _connections[sockfd]->SetEvent(new_event);
        _epoller_ptr->Modevent(sockfd,new_event);
    }

    //删除对应的套接字,及其_epoll_ptr监听的设置
    void DelConnection(int sockfd)
    {
        _epoller_ptr->DelEvent(sockfd);

        _connections.erase(sockfd);

        close(sockfd);

        LOG(LogLevel::INFO)<<"CLIENT QUIT:"<<sockfd;
    }

    //打印所有监听的套接字
    void PrintConnection()
    {
        std::cout<<"当前Reactor正在进行管理的fd list:";
        for(auto& conn:_connections)
        {
            std::cout<<conn.second->GetSockFd()<<" ";
        }
        std::cout<<"\r\n";
    }
    ~Reactor()
    {
    }
    void Stop()
    {
        _isrunning = false;
    }

private:
    // Epoll模型
    std::unique_ptr<Epoller> _epoller_ptr;
    // 所有的连接
    std::unordered_map<int, std::shared_ptr<Connection>> _connections;
    // 执行位
    bool _isrunning;
    // 可执行的套接字
    struct epoll_event _revs[revs_num];
};
